home *** CD-ROM | disk | FTP | other *** search
/ Resource Library: Multimedia / Resource Library: Multimedia.iso / archvrs / msdos / unshar / shar_cmd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1986-09-25  |  9.2 KB  |  458 lines

  1. /*
  2.  *                ---   SHAR_CMD.C   ---
  3.  *            ---   Command Portion of   ---
  4.  *                 ---   UNSHAR.C   ---
  5.  *
  6.  *          ---   Copywrite 24 September, 1986   ---
  7.  *              ---    John Birchfield      ---
  8.  *              ---    411 Crane Ave.       ---
  9.  *              ---    Turlock, CA  95380   ---
  10.  *              ---      (209) 634-6243     ---
  11.  *
  12.  *    Program to decode files created by the shell archive { shar }
  13.  *    utility on Un*x machines or pc's.  Current capabilities include
  14.  *
  15.  *    1.    Able to unshar into a user specified directory or subdirectory
  16.  *        as specified by a command line option { -Ddirectory_name }
  17.  *
  18.  *    2.    Recognizes the following commands
  19.  *            cat, sed, uudecode, mkdir, chdir, 
  20.  *            {test -f, test -d, test <number -ne wc ... }
  21.  *
  22.  *    3.    Can handle shar scripts created with the
  23.  *            Options { -a -v -p -b -c -d }
  24.  *
  25.  *    4.    Successfully traverses directories and sub-directories
  26.  *        creating the necessary subdirectories as necessary.
  27.  *
  28.  *    CAVEATS:
  29.  *        Word Counting between Un*x machines and pc's just isn't
  30.  *        gonna work out too well.  The \r\n - \n thing is not
  31.  *        an easy thing to work around - and to be quite frank
  32.  *        I just ain't up to it.
  33.  *
  34.  *    Program written for the Desmet (C-Ware) C Compiler Version 2.61
  35.  *    not all of the routines in DOS_C.C and DOS_A.A are used by this
  36.  *    program.  The program consists of the following modules:
  37.  *        UNSHAR.C
  38.  *        SHAR_CMD.C
  39.  *        DOS_C.C
  40.  *        DOS_A.A
  41.  *
  42.  *    This program is hereby placed in the public domain for 
  43.  *    non-commersial use.
  44.  *
  45.  */
  46.  
  47. # include <stdio.h>
  48. # include "unshar.h"
  49. # include "dos.h"
  50.  
  51.  
  52.  
  53.  
  54. /*
  55.  *    P_ERROR ()    -    p_error () is a simple routine for
  56.  *        displaying a message consisting of a sequence of
  57.  *        strings thru stdout.  The first parameter is an
  58.  *        integer { if non-zero an exit occurs } the last
  59.  *        parameter is an empty string.
  60.  */
  61.  
  62. void p_error (no, args)
  63. int no;
  64. char *args;
  65. {
  66.     char **tmp;
  67.     tmp = &args;
  68.     while (**tmp)
  69.         fputs (*tmp++, stdout);
  70.     if (no)
  71.         _exit (no);
  72. }
  73.  
  74.  
  75.  
  76.  
  77. /*
  78.  *    DO_CD ()    -    change directories
  79.  */
  80.  
  81. int do_cd (fp)
  82. FILE *fp;
  83. {
  84.     char buf [20];
  85.     get_tok (buf, fp);
  86.     return (chdir (buf));
  87. }
  88.  
  89.  
  90.  
  91.  
  92. /*
  93.  *    DO_MKDIR ()    -    make a directory
  94.  */
  95.  
  96. int do_mkdir (fp)
  97. FILE *fp;
  98. {
  99.     char buf [20];
  100.     get_tok (buf, fp);
  101.     return (mkdir (buf));
  102. }
  103.  
  104.  
  105.  
  106.  
  107. /*
  108.  *    DO_EXIT ()    -    Bye Bye
  109.  */
  110.  
  111. void do_exit (fp)
  112. FILE *fp;
  113. {
  114.     char buf [20];
  115.     get_tok (buf, fp);
  116.     exit (atoi (buf));
  117. }
  118.  
  119.  
  120.  
  121.  
  122. /*
  123.  *    DO_CAT ()    -    get the destination filename, get the
  124.  *        terminating string open the file and pass the contents
  125.  *        of the input stream to it until the termination flag
  126.  *        is recognized.
  127.  */
  128.  
  129. void do_cat (fp)
  130. FILE *fp;
  131. {
  132.     FILE *f_out;
  133.     char delimiter [80], fname [65], *dp,
  134.          buf [256],
  135.          tmp [15];
  136.     int len;
  137.     
  138.     fname [0] = delimiter [0] = '\0';
  139.     do {
  140.         get_tok (tmp, fp);
  141.         if (strncmp (tmp, "<<", 2)==0)
  142.             get_tok (delimiter, fp);
  143.         else if (strncmp (tmp, ">", 1)==0)
  144.             get_tok (fname, fp);
  145.     } while (fname [0]=='\0' || delimiter [0]=='\0');
  146.  
  147.     fix_file_name (fname);
  148.     if ((f_out=creat (fname))==-1)
  149.         p_error (1, "Cat Can't Create '", fname, "'\n", "");
  150.     dp = &delimiter [1];
  151.     len = strlen (dp);
  152.     while (fgets (buf, 256, fp)) {
  153.         if (strncmp (dp, buf, len)==0)
  154.             break;
  155.         fputs (buf, f_out);
  156.     }
  157.     fclose (f_out);
  158. }
  159.  
  160.  
  161.  
  162.  
  163. /*
  164.  *    DO_SED ()    -    do_sed () works just like do_cat ()
  165.  *        except that the command line has the sed s/ //
  166.  *        translation parameter in it { one more token }
  167.  *        Command lines are of the form
  168.  *            sed 's/^    X//' << \SHAR_EOF > '.cshrc'
  169.  */
  170.  
  171. void do_sed (fp)
  172. FILE *fp;
  173. {
  174.     FILE *f_out;
  175.     char  replace [40], delimiter [80], fname [65], *dp, *rp,
  176.           buf [256], *nbuf,
  177.           tmp [15];
  178.     int len, rlen;
  179.  
  180.     get_tok (replace, fp);
  181.     fname [0] = delimiter [0] = '\0';
  182.     do {
  183.         get_tok (tmp, fp);
  184.         if (strncmp (tmp, "<<", 2)==0)
  185.             get_tok (delimiter, fp);
  186.         else if (strncmp (tmp, ">", 1)==0)
  187.             get_tok (fname, fp);
  188.     } while (fname [0]=='\0' || delimiter [0]=='\0');
  189.  
  190.     fix_file_name (fname);
  191.     rp = &replace [3];
  192.     if (index (rp, '/'))
  193.         *index (rp, '/') = '\0';
  194.     rlen = strlen (rp);
  195.     nbuf = &buf [0] + rlen;
  196.     if ((f_out=creat (fname))==-1)
  197.         p_error (1, "Cat Can't Create '", fname, "'\n", "");
  198.     dp = &delimiter [1];
  199.     len = strlen (dp);
  200.     while (fgets (buf, 256, fp)) {
  201.         if (strncmp (dp, buf, len)==0)
  202.             break;
  203.         if (strncmp (rp, buf, rlen)==0)
  204.             fputs (nbuf, f_out);
  205.         else    
  206.             fputs (buf, f_out);
  207.     }
  208.     fclose (f_out);
  209.     ;
  210. }
  211.  
  212.  
  213.  
  214. /*
  215.  *    DO_UUDECODE ()    -    do_uudecode () handles uudecoding
  216.  *        chores in the same way that do_cat () and do_sed ()
  217.  *        process their input.  There are differnces in that
  218.  *        the uuencoded stream has it's filename as the
  219.  *        beginning of the file and not imbedded in
  220.  *        the uudecode command line.
  221.  */
  222.  
  223. void do_uudecode (fp)
  224. FILE *fp;
  225. {
  226.     FILE *f_out;
  227.     char delimiter [80], fname [65], *dp,
  228.          buf [256];
  229.     int len;
  230.     
  231.     do {
  232.         get_tok (delimiter, fp);
  233.     } while (strncmp (delimiter, "<<", 2));
  234.  
  235.     get_tok (delimiter, fp);
  236.     dp = &delimiter [1];
  237.     len = strlen (dp);
  238.     fname [0] = '\0';
  239.     do {
  240.         if (get_tok (fname, fp)==0)
  241.             p_error (2, "Uudecode: No begin statement\n", "");
  242.     } while (strcmp (fname, "begin"));
  243.     get_tok (fname, fp);
  244.     get_tok (fname, fp);
  245.     fix_file_name (fname);
  246.     if ((f_out=creat (fname))==-1)
  247.         p_error (1, "Uudecode Can't Create '", fname, "'\n", "");
  248.  
  249.     decode(fp, f_out);
  250.  
  251.     if (fgets(buf, sizeof buf, fp) == NULL || strcmp(buf, "end\n"))
  252.         p_error (5, "Uudecode No end line\n", "");
  253.     while (fgets (buf, sizeof (buf), fp))
  254.         if (strncmp (buf, dp, len)==0)
  255.             break;
  256.     fclose (f_out);
  257. }
  258.  
  259.  
  260.  
  261.  
  262. /*
  263.  * copy from in to out, decoding as you go along.
  264.  */
  265.  
  266. #define DEC(c)    (((c) - ' ') & 077)
  267.  
  268. decode(in, out)
  269. FILE *in;
  270. FILE *out;
  271. {
  272.     char buf[80];
  273.     char *bp;
  274.     int n;
  275.  
  276.     for (;;) {
  277.         /* for each input line */
  278.         if (fgets(buf, sizeof buf, in) == NULL)
  279.             p_error (10, "Uudecode Short file\n", "");
  280.  
  281.         n = DEC(buf[0]);
  282.         if (n <= 0)
  283.             break;
  284.         bp = &buf[1];
  285.         while (n > 0) {
  286.             outdec(bp, out, n);
  287.             bp += 4;
  288.             n -= 3;
  289.         }
  290.     }
  291. }
  292.  
  293.  
  294.  
  295.  
  296. /*
  297.  * output a group of 3 bytes (4 input characters).
  298.  * the input chars are pointed to by p, they are to
  299.  * be output to file f.  n is used to tell us not to
  300.  * output all of them at the end of the file.
  301.  */
  302.  
  303. outdec(p, f, n)
  304. char *p;
  305. FILE *f;
  306. {
  307.     int c1, c2, c3;
  308.  
  309.     c1 = DEC(*p) << 2 | DEC(p[1]) >> 4;
  310.     c2 = DEC(p[1]) << 4 | DEC(p[2]) >> 2;
  311.     c3 = DEC(p[2]) << 6 | DEC(p[3]);
  312.     if (n >= 1)
  313.         fputc(c1, f);
  314.     if (n >= 2)
  315.         fputc(c2, f);
  316.     if (n >= 3)
  317.         fputc(c3, f);
  318. }
  319.  
  320.  
  321.  
  322.  
  323. /*
  324.  *    DO_TEST ()    -    do_test () tries to perform the test
  325.  *        requested by the shar script.  At the moment the 
  326.  *        following tests are recognized
  327.  *
  328.  *        test ! -d directoryname
  329.  *        test -f filename
  330.  *        test <number> -ne wc ...  do a word count of
  331.  *                                  the file
  332.  */
  333.  
  334. int do_test (fp)
  335. FILE *fp;
  336. {
  337.     FILE *tfp;
  338.     
  339.     char flag [10], fname [100];
  340.     int    invert = FALSE;
  341.     long    wc_arg;
  342.     get_tok (flag, fp);
  343.     if (strcmp (flag, "!")==0) {
  344.         invert = TRUE;
  345.         get_tok (flag, fp);
  346.     }
  347.     if (strcmp (flag, "-f")==0) {
  348.         get_tok (fname, fp);
  349.         fix_file_name (fname);
  350.         if (tfp=fopen (fname, "r"))
  351.             fclose (tfp);
  352.     }
  353.     else if (strcmp (flag, "-d")==0) {
  354.         get_tok (fname, fp);
  355.         fix_file_name (fname);
  356.         if (tfp=(FILE *) opendir (fname))
  357.             closedir (tfp);
  358.     }
  359.     else if (isdigit(flag [0])) {
  360.         wc_arg = atol (flag);
  361.         get_tok (flag, fp);
  362.         if (strcmp (flag, "-ne")==0) {
  363.             get_tok (fname, fp);
  364.             return ((w_cnt (fname, wc_arg)));
  365.         }
  366.         else {
  367.             cmd_init ();
  368.             return ((int) test_flag);
  369.         }
  370.     }
  371.     else {        
  372.         cmd_init ();
  373.         return ((int) test_flag);
  374.     }
  375.     return ((invert)?!(tfp):tfp);
  376. }
  377.  
  378.  
  379.  
  380.  
  381. /*
  382.  *    W_CNT ()    -    This part of test is a separate function
  383.  *        'cause I don't like to nest that deep.  by the time
  384.  *        w_cnt () has been passed control it's broken down the
  385.  *        shar script command of the form
  386.  *            if test 488 -ne "`wc -c < 'FileName'`"
  387.  *        to
  388.  *            `wc -c < 'FileName'`
  389.  *        which is not too hard to extract the filename from
  390.  */
  391.  
  392. int w_cnt (name, arg)
  393. char *name;
  394. long  arg;
  395. {
  396.     char filename [65];
  397.     struct stat statbuf;
  398.     char *np, *index (), *rindex ();
  399.     np = index (name, '\'') +1;
  400.     *index (np, '\'') = '\0';
  401.     strcpy (filename, np);
  402.     fix_file_name (filename);
  403.     stat (filename, &statbuf);
  404.     if (statbuf.st_size != arg)
  405.         return (1);
  406.     return (0);
  407. }
  408.  
  409.  
  410.  
  411.  
  412. /*
  413.  *    DO_SKIP ()    -    do_skip () passes thru the input until
  414.  *        he has determined that the command that would have
  415.  *        been processed at this point in the stream has been
  416.  *        flushed.
  417.  */
  418.  
  419. void do_skip (fp)
  420. FILE *fp;
  421. {
  422.     char buf [256], delimiter [80], *dp;
  423.     int len;
  424.  
  425.     do {
  426.         get_tok (delimiter, fp);
  427.     } while (strncmp (delimiter, "<<", 2));
  428.     get_tok (delimiter, fp);
  429.     dp = &delimiter [1];
  430.     len = strlen (dp);
  431.     while (fgets (buf, sizeof (buf), fp))
  432.         if (strncmp (dp, buf, len)==0)
  433.             break;
  434.     cmd_init ();
  435. }
  436.  
  437.  
  438.  
  439.  
  440. /*
  441.  *    FIX_FILE_NAME ()    -     does two things
  442.  *        (1)  strips off any leading path identifiers
  443.  *        (2)  appends the leading path header to the
  444.  *             filename presented to it.
  445.  */
  446.  
  447. void fix_file_name (s)
  448. char *s;
  449. {
  450.     char buf [65], *tp, *rindex ();
  451.     strcpy (buf, root_dir);
  452.     if (tp=rindex (s, '/'))
  453.         strcat (buf, tp+1);
  454.     else
  455.         strcat (buf, s);
  456.     strcpy (s, buf);
  457. }
  458.